﻿using System;
using System.Linq;
using System.Threading;
using System.Windows.Input;
using MEF_Test.Bricks;
using MEF_Test.Bricks.Wrappers;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.Regions;

namespace MEF_Test.VideoRenderer.LocalVideoRenderer
{
    using System.ComponentModel;
    using MEF_Test.Contracts;
    using MEF_Test.Subtitles;

    using WPFMediaKit.DirectShow.Controls;

    public class VideoRendererViewModel : IVideoRendererViewModel
    {
        private readonly IRegionManager _regionManager;

        private readonly IBrowserNodeViewModel _browserNodeViewModel;

        private readonly ISubtitleHandler _selectedSubtitle;

        public DelegateCommand<object> MediaPositionChangedCommand { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="VideoRendererViewModel"/> class.
        /// </summary>
        /// <param name="regionManager">The region manager.</param>
        /// <param name="browserNodeViewModel">The browser node view model.</param>
        /// <param name="selectedSubtitle">The selected subtitle.</param>
        /// <param name="playbackControlsViewFactory">The playback controls view factory.</param>
        /// <param name="eventAggregator"></param>
        /// <remarks>not optimized for reading without subtitle.</remarks>
        public VideoRendererViewModel(IRegionManager regionManager, IBrowserNodeViewModel browserNodeViewModel, ISubtitleHandler selectedSubtitle, IPlaybackControlsViewFactory playbackControlsViewFactory, IEventAggregator eventAggregator)
        {
            if (regionManager == null)
            {
                throw new ArgumentNullException("regionManager");
            }

            if (browserNodeViewModel == null)
            {
                throw new ArgumentNullException("browserNodeViewModel");
            }


            SeekMediaPositionCommand = new DelegateCommand<object>(SeekMediaPositionCommandChanged);
            MediaPositionChangedCommand = new DelegateCommand<object>(MediaPositionChanged);
            ShowPlaybackControlsCommand = new DelegateCommand(executeShowPlaybackControls);
            ShowLocalControlsCommand = new DelegateCommand(executeShowLocalControls);

            FileHandler = browserNodeViewModel.FileHandler;
            _regionManager = regionManager;
            _playbackControlsViewFactory = playbackControlsViewFactory;            
            _browserNodeViewModel = browserNodeViewModel;
            _selectedSubtitle = selectedSubtitle;

            _displayedSubtitleText = "Subtitles";      
            PrepareNextSubtitleLine(0);
        }

        public ICommand SeekMediaPositionCommand { get; set; }

        private void SeekMediaPositionCommandChanged(object o)
        {
            var position = (long) o;
            PrepareNextSubtitleLine(position);
        }

        private void executeShowPlaybackControls()
        {
            var localControlsRegion = _regionManager.Regions["LocalControls"];
            var playbackControlsView = localControlsRegion.GetView("PlaybackControlsView");
            if (playbackControlsView == null)
            {
                playbackControlsView = _playbackControlsViewFactory.Create();
                localControlsRegion.Add(playbackControlsView);
            }
            localControlsRegion.Activate(playbackControlsView);
        }

        private void MediaPositionChanged(object o)
        {
            var position = (long) o / 10000.0;
            if (position < _subtitleEndTime && position > _subtitleStartTime)
            {
                DisplayedSubtitleText = _subtitleText;
                PrepareNextSubtitleLine(position);
            }
        }

        private void PrepareNextSubtitleLine(double position)
        {
            ISubtitleEntry subtitleEntry = _selectedSubtitle.SubtitleEntries.First(o => o.Start.TotalMilliseconds > position);
            _subtitleText = subtitleEntry.DialogLine;
            _subtitleStartTime = subtitleEntry.Start.TotalMilliseconds;
            _subtitleEndTime = _subtitleStartTime + subtitleEntry.Duration.TotalMilliseconds;
        }


        private string _displayedSubtitleText;
        private string _subtitleText;
        private double _subtitleStartTime;
        private double _subtitleEndTime;
        private readonly IPlaybackControlsViewFactory _playbackControlsViewFactory;

        public string DisplayedSubtitleText
        {
            get
            {
                return this._displayedSubtitleText;
            }

            set
            {
                if (value != _displayedSubtitleText)
                {
                    this._displayedSubtitleText = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs("DisplayedSubtitleText"));
                    }
                }
            }
        }

        /// <summary>
        /// Is executed when the <see cref="ShowLocalControlsCommand"/> command is executed.
        /// </summary>
        private void executeShowLocalControls()
        {
            // Show the controls
            var localControlsRegion = _regionManager.Regions["LocalControls"];
            var localControlsView = localControlsRegion.GetView("LocalControlsView");
            localControlsRegion.Activate(localControlsView);
        }

        /// <summary>
        /// Gets or sets the file handler.
        /// </summary>
        /// <value>The file handler.</value>
        public IFileHandler FileHandler { get; set; }

        /// <summary>
        /// Gets or sets the show local controls command.
        /// </summary>
        /// <value>The show local controls command.</value>
        public DelegateCommand ShowLocalControlsCommand { get; set; }

        public DelegateCommand ShowPlaybackControlsCommand { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}